import numpy as np
import math
from scipy import integrate             # 调用积分
import matplotlib.pyplot as plt         # 绘图
from mpl_toolkits.mplot3d import Axes3D # 绘图3D



    
class PLOT_3D(object):
    #___________________________________________________________________________________________________________________
    #@ 初始化
    def __init__(self,x_list=[0,5,100],y_list=[0,5,100]):
        self.get_x_y(x_list,y_list)
        self.get_z()
    #___________________________________________________________________________________________________________________
    #@ 获得 x-y 网格
    def get_x_y(self,x_list,y_list):
        x_vals = np.linspace(x_list[0],x_list[1],x_list[2])
        y_vals = np.linspace(y_list[0],y_list[1],y_list[2])
        self.X_MAT,self.Y_MAT = np.meshgrid(x_vals,y_vals)  # 创建网格：将x_vals一维数组，扩展len(y_vals)行；将y_vals一维数组，扩展len(x_vals)列
    #___________________________________________________________________________________________________________________
    #@ 获得 z轴 的值
    def get_z(self):
        x_index = self.X_MAT.shape[0]  # X_MAT 的 shape[0] 是 y_vals 的个数，但是 shape[0] 在 np 里是 x 轴，第一维。
        y_index = self.X_MAT.shape[1]  # X_MAT 的 shape[1] 是 x_vals 的个数
        self.Z_MAT = np.zeros((x_index,y_index))
        for x in range(x_index):
            for y in range(y_index):
                self.Z_MAT[x,y] = self.function(self.X_MAT[x,y],self.Y_MAT[x,y])
    #___________________________________________________________________________________________________________________
    #@ 显示
    def show(self,title='标题',x_label='x 轴',y_label='y 轴',z_label='z 轴'):
        #// 3D画布设置
        ax = Axes3D(plt.figure())                   # plt.figure()：生成二维画布；Axes3D(plt.figure())：生成3维画布
        plt.rcParams['font.sans-serif']=['SimHei']  # 显示汉字
        plt.rcParams['axes.unicode_minus'] = False  # 显示汉字
        #// 画布标题 坐标轴标签
        ax.set_title(title)         # 标题
        ax.set_xlabel(x_label)      # x轴含义
        ax.set_ylabel(y_label)      # y轴含义
        ax.set_zlabel(z_label)      # z轴含义
        #// 显示
        # rstride:行之间的跨度；cstride:列之间的跨度；cmap：颜色映射表
        ax.plot_surface(self.X_MAT,self.Y_MAT,self.Z_MAT,rstride=1,cstride=1,cmap="rainbow")
        plt.show()
    #___________________________________________________________________________________________________________________
    #@ 目标函数
    #! 类内改动
    def function(self,x,y):
        
        z = x + y
        
        # z = math.sin(2*x)+math.cos(2*y)
        
        z = 0*x + math.log(y)
        # z=1/y
        # z=math.log(x) + y
        # z = x+2*y
        # z=math.log(x) + math.exp(y)
        # z= 1/x + 1
        # z=x+1/20*(math.exp(y))
        # z=1+math.exp(y)
        # z=1/x+math.exp(y)
        # z = 10*np.sin(0.05*x) + np.cos(2*y)
        # z = np.sin(0.05*x) + np.cos(2*y)
        # z = 0.05*np.cos(0.05*x) - 2*np.sin(2*y)
        # z = np.cos(0.5*x) - np.sin(0.2*y)
        
        return z



#_______________________________________________________________________________________________________________________
#@ run
#! 两处改动
obj = PLOT_3D([1,6,100],[1,6,100])
obj.show(title='y = x3 + 2·x4',x_label='0·x1',y_label='ln(x2)',z_label='y = 0·x1 + ln(x2)')